'''
==============================================
Created on 22nd, November 2011
@author: Miguel de Campos Rodrigues - no. 5959
==============================================
'''
# -*- coding: utf-8 -*-

from modules.BeautifulSoup import BeautifulSoup as BS

import os
import csv
import sqlite3
import urllib2
import numpy
import matplotlib.pyplot as plt
import SocketServer
import SimpleHTTPServer
import thread
from urllib2 import HTTPError
from urllib2 import URLError

class htmlAnalyser:
    '''
    This class gets unformatted text from
    a web page.
    '''
    httpd = None
    __statusCode = 200
    __statusDescription = "OK"
    __url = ""
    __errorMsg = ""
    
    soup = None;
    def __init__(self):
        '''
            constructor
        '''
        pass

    def __str__(self):
        if self.soup == None:
            return "Error: No source avaliable."
        else:
            return self.soup.prettify("utf-8").decode("utf-8", "replace")
          
    def browse(self, URL):
        try:
            self.__url = URL
            htmlResponse = urllib2.urlopen((self.__url))
            self.soup = BS.BeautifulSoup(htmlResponse)
            self.__statusCode = htmlResponse.code
            self.__statusDescription = htmlResponse.msg
            pass
        except HTTPError as ex:
            self.__statusCode = ex.code
            self.__statusDescription = ex.msg
            self.__errorMsg = ""
            pass
        except URLError as ex:
            self.__statusCode = 1000     #Non standard status code.
            self.__statusDescription = "URL ERROR"
            self.__errorMsg = reduce(    #Error described Here
                lambda str1, value: str1.join(" - ".join(value)),
                ex.args)
        except Exception as ex:
            self.__statusCode = 1001     #Non standard status code.
            self.__statusDescription = "UNKNOWN ERROR"
            self.__errorMsg = reduce(    #Error described Here
                lambda str1, value: str1.join(" - ".join(value)),
                ex.args)
        return self.__statusCode
    
    def getStatusCode(self):
        return self.__statusCode

    def getStatusDescription(self):
        return self.__statusDescription
    
    def getErrorMessage(self):
        return self.__errorMsg
    
    def getElementByID(self, reference):
        return self.soup.find(attrs={"id" : reference})
    
    def getElementsByTag(self, elTag):
        return self.soup.findAll(elTag)

    def clearContents(self):
        self.__statusCode = 200
        self.__statusDescription = "OK"
        self.__url = ""
        self.__errorMsg = ""
        if self.soup != None:
            self.soup.close()
        pass

    #### Httpd Server ####
    def initServer(self, workingDir=None, port=80):
        if workingDir != None:
            os.chdir(workingDir)
            pass
        self.handler = SimpleHTTPServer.SimpleHTTPRequestHandler
        self.httpd = SocketServer.TCPServer(("", port), self.handler)
        self.__serverThread = thread(target=self, args=(port))
        self.__serverThread.start()
        pass
        
    def run(self, port=80):
        ## Server thread ##  
        print "serving at port ", port
        self.httpd.serve_forever();
        pass
    
    def stopServer(self):
        if self.httpd != None and thread._count() > 0:
            self.httpd.shutdown()
            thread.exit();
            print "Server stopped."
            pass
        pass
    #### Httpd Server ####
#Class
    
class CSVtoSQLite:
    
    __sqliteDBuri = ""
    
    '''
        Initializes a new instance of CSVtoSQLite Class.
        Parameters:
            sqliteDBfile: the SQLite 3 database file path.
            example: "C:\sqlite\db\fooBar.db"
    '''
    def __init__ (self, sqliteDBfile="database.db"):
        self.__sqliteDBuri = sqliteDBfile
        pass
    
    '''
        Tries to load CSV table file.
        If it loads successfully returns True, otherwise False.
    '''
    def loadCSV(self, filePath):
        openedFile = open(filePath, "rb")
        openedFile.next() #Skip headers
        return  csv.reader(
            map(lambda line: line.decode('utf-8'), openedFile),
            delimiter=',', quotechar='"')
        pass
    
    '''
        Sends the table into the SQLite Database.
    '''
    def commit(self, table):
        '''
        Detecta os cabecalhos
        Se os cabecalhos forem compativeis com a tabela entao continua.
        Se nao existir tabela com o mesmo nome, cria a tabela.
        Se a tabela conter valores repetidos, cria uma nova relacionada com esses valores
        '''
        if os.path.isfile(self.__sqliteDBuri) == False:
            #Create database file if it doesn't exist
            newFile = open(self.__sqliteDBuri, 'w')
            newFile.write('')
            newFile.close()
            pass
        connection = sqlite3.connect(self.__sqliteDBuri)
        connection.text_factory = sqlite3.OptimizedUnicode
        cursor = connection.cursor()
        cursor.executescript("""CREATE TABLE IF NOT EXISTS docentes 
                       (Cod_Docente INT, Nome VARCHAR(200), Grau VARCHAR(50),
                       Curso VARCHAR(50), Categoria VARCHAR(50),
                       Regime VARCHAR(50), Ano INT,
                       Tipo_Estabelecimento VARCHAR(100),
                       Nome_Estabelecimento VARCHAR(100))""")
        for row in self.__ripData(table):
            cursor.execute("""INSERT INTO docentes VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", row)
            pass
        connection.commit()
        connection.close()
    
    '''
        Makes a custom query to the SQLite database.
    '''
    def sqlQuery(self, queryString):
        connection = sqlite3.connect(self.__sqliteDBuri)
        connection.text_factory = sqlite3.OptimizedUnicode
        cursor = connection.cursor()
        cursor.execute(queryString)
        connection.commit()
        yield map(lambda x: x,map(lambda y: unicode(y, "utf-8"),
                                  cursor.fetchall()))
        cursor.close()
        connection.close()
        pass
    
    '''
        Converts the data to be compatible by the database.
    '''
    def __ripData(self, table):
        return map(lambda row: map(
            lambda cell: cell.replace('\"', '\"\"'),row), table)
#Class

class StatsGenerator():
    chart = plt.Figure()    
    def __init__(self, parent):
        pass
    
    def setMode(self, mode):
        pass
    
    def getGroupList(self):
        pass
    
    def getSelectionList(self, groupList):
        
        pass
    
    def getTable(self):
        
        pass
    
    def getGraph(self):
        
        pass
#Class